const cheerio = require('cheerio');
const fetch = require("node-fetch");
var fs = require("fs");
var path = require("path");
var url = require("url");

/**
 * @desc  获取静态html
 * @param {String} u URL 
 * @return {Promise} 
 */
function getHTML(u, c) {
    return fetch(u, c || {
        method: 'GET',
        headers: {
            'Content-Type': 'text/html;charset=utf-8',
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
        },
    }).then(res => res.text());
};



/**
 * @desc  类似jQuery操作
 * @param {String} h HTML 
 * @return {Object} 
 */
function jQuery(h) {
    return cheerio.load(h, { decodeEntities: false });
}
/**
 * @desc  获取buffer
 * @param {String} u URL 
 * @return {Promise} 
 */
function fetchB(u, c) {
    return fetch(u, c || {
        method: 'GET',
        headers: { 'Content-Type': 'application/octet-stream' },
    }).then(res => res.buffer());
}
/**
 * @desc  下载文件
 * @param {String} u URL 
 * @param {String} p 保存路径
 * @return {Promise} 
 */
function download(u, p, c) {
    return new Promise(function (resolve, reject) {
        fetchB(u, c).then(_ => {
            fs.writeFile(p, _, "binary", function (err) {
                if (err) reject(err);
                else resolve(p);
            });
        }).catch(reject);
    });
    //download(url,"??&&**xlsx.utils.js").catch(console.log); 
}

/**
* @desc  URL转本地路径
* @param {String} u URL
* @param {String} p 路径前缀
* @return {String} 
*/
function url2LocalPath(u, p) {
    let info = url.parse(u);
    return path.join(p || "./", info.host + info.pathname);
}

/**
* @desc  递归创建目录 同步方法
* @param {String} dirname 路径
* @return {Boolean} 
*/
function mkDirsSync(dirname) {
    try {
        if (fs.existsSync(dirname)) {
            return true;
        } else {
            if (mkDirsSync(path.dirname(dirname))) {
                fs.mkdirSync(dirname);
                return true;
            }
        }
    }
    catch (err) {
        return false;
    }
}

/**
* @desc  保存文件前处理
* @param {String} p 路径 
*/
function mkFileDirs(p) {
    return mkDirsSync(path.dirname(p))
}
/**
* @desc  递归文件夹
* @param {String} filePath 路径 
* @param {Function} isF 
* @param {Function} isD
*/
function deepFiles(filePath, isF, isD) {
    let dirs = fs.readdirSync(filePath);
    if (dirs.length > 0) {
        dirs.forEach(function (filename) {
            let filedir = path.join(filePath, filename);
            if (fs.statSync(filedir).isFile()) {
                if (typeof isF == "function") isF(filename, filePath, filedir);
            } else {
                let r = true;
                if (typeof isD == "function") {
                    r = isD(filedir);
                }
                if (r != false) {
                    deepFiles(filedir, isF, isD);
                }
            }
        });
    }
}
/**
* @desc  删除文件夹
* @param {String} path 路径  
*/
function deleteFolder(path) {
    var files = [];
    if (fs.existsSync(path)) {
        files = fs.readdirSync(path);
        files.forEach(function (file, index) {
            var curPath = path + "/" + file;
            if (fs.statSync(curPath).isDirectory()) { // recurse
                deleteFolder(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
}

/**
 * 
 * @desc 生成指定范围[min, max]的随机数
 * @param  {Number} min 
 * @param  {Number} max 
 * @return {Number} 
 */
function randomNum(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}


/**
* @desc  获取当前系统外网ip   
* @return {String}
*/
async function getIp() {
    let f = function (u) {
        return fetch(u, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
            },
        }).then(res => res.json());
    };
    let fns = [
        async () => (await f("http://jsonip.com"))['ip'],
        async () => (await f("http://httpbin.org/ip"))['origin'],
        async () => (await f("https://api.ipify.org/?format=json"))['ip']
    ];
    try {
        return await fns[randomNum(0, fns.length - 1)]();
    } catch (error) {
        return null;
    }
}
/**
 * 
 * @desc   全部替换
 * @param  {String} 原始字符串
 * @param  {String} 搜索字符串
 * @param  {String} 替换字符串
 * @return {String}
 */
function replaceAll(s0, s1, s2) {
    return s0.replace(new RegExp(s1, "gm"), s2);
}

module.exports = {
    randomNum: randomNum,
    getHTML,
    mkFileDirs,
    url2LocalPath,
    download,
    mkDirsSync,
    jQuery,
    fetchB,
    exists: fs.existsSync,//存在路径
    extname: path.extname,//获取扩展名
    filename: path.basename,//获取文件名
    dirname: path.dirname,//获取文件夹名
    rmd: deleteFolder,//删除文件夹
    rmf: fs.unlinkSync,//删除文件
    moveFile: function (op, np) { fs.renameSync(op, np); },//移动文件
    copyFile: function (op, np) { fs.writeFileSync(np, fs.readFileSync(op)); },//复制文件
    readJSON: function (p) { return JSON.parse(fs.readFileSync(p)); },//读取json
    writeJSON: function (p, d) { fs.writeFileSync(p, JSON.stringify(d)); },//保存json
    readText: function (p) { return fs.readFileSync(p, 'utf-8'); },//读取文本 
    writeText: fs.writeFileSync,//写入文件
    deepFiles: deepFiles,
    replace: replaceAll,
    getIp: getIp,
    formatQuery: function (s) {
        if (typeof s === "object") {
            let sl = [];
            for (let k in s) sl.push(k + "=" + a[k]);
            return sl.join("&");
        } else {
            let qs = {}, vars = s.split("&");
            for (let i of vars) {
                let itm = i.split("=");
                qs[itm[0]] = itm[1];
            }
            return qs;
        }
    },
    fileNm(str) { let all = ["\\", "/", ":", "*", "?", "\"", "<", ">", "|", "\r", "\n"]; return str.split("").map(_ => (all.indexOf(_) >= 0 ? "_" : _)).join(""); }
};
